
#include "nrf24_device.h"
//low level api for cmd+data writing
//return current value of STATUS reg
static char nrf_cmd_write(char cmd, char* buf, char wrlen)
{
	char status = 0;
	NRF_CSN_LOW();   //Every new command must be started by a high to low transition on CSN
	NRF_DELAY_uS(1); //wait for Data Valid on  MISO 
	status = NRF_SPI_RW(cmd);
	while(wrlen>0)
	{//loop for sending bytes
		NRF_SPI_RW(*buf);
		buf++;
		wrlen--;
	}
	NRF_CSN_HIGH();  //set CSN before return  
	NRF_DELAY_uS(1); //keep CSN high for 1us, CSN Inactive time must no less than 50nS
	return status;
}
//low level api for cmd+data reading
//return current value of STATUS reg
static char nrf_cmd_read(char cmd, char* buf, char rdlen)
{
	char status = 0;
	NRF_CSN_LOW();
	NRF_DELAY_uS(1);
	status = NRF_SPI_RW(cmd);
	while(rdlen>0)
	{//loop for reading bytes
		*buf = NRF_SPI_RW(0xFF);
		buf++;
		rdlen--;
	}
	NRF_CSN_HIGH(); 
	NRF_DELAY_uS(1);
	return status;
}
//low level api for cmd writing
//return current value of STATUS reg
static char nrf_write_cmd_only(char cmd)
{
	return nrf_cmd_write(cmd, (char*)0, 0);
}
/********************************
Descrip:  Read multi-bytes from a register
Arg    :  
          regadr - 5 bit Register Map Address
          buf    - buffer for data saving
          rdlen  - number of bytes to read
Return :  current value of STATUS reg
*********************************/
char nrf_reg_read_buf(char regadr, char* buf, char rdlen)
{
	return nrf_cmd_read(NRF_CMD_R_REG(regadr), buf, rdlen);
}
/********************************
Descrip:  Read byte value from a register
Arg    :  regadr - 5 bit Register Map Address
Return :  the byte read back
*********************************/
char nrf_reg_read_byte(char regadr)
{
	char ret = 0;
	nrf_cmd_read(NRF_CMD_R_REG(regadr), &ret, 1);
	return ret;
}
/********************************
Descrip:  write multi-bytes to a register
Arg    :  
          regadr - 5 bit Register Map Address
          buf    - buffer for data saving
          wrlen  - number of bytes to write
Return :  current value of STATUS reg
*********************************/
char nrf_reg_write_buf(char regadr, char* buf, char wrlen)
{
	return nrf_cmd_write(NRF_CMD_W_REG(regadr), buf, wrlen);
}
/********************************
Descrip:  write byte to a register
Arg    :  
          regadr - 5 bit Register Map Address
          val    - byte to write
Return :  current value of STATUS reg
*********************************/
char nrf_reg_write_byte(char regadr, char val)
{
	return nrf_cmd_write(NRF_CMD_W_REG(regadr), &val, 1);
}
/********************************
Descrip:  flush RX FIFO
Arg    :  none
Return :  current value of STATUS reg
*********************************/     
char nrf_rx_flush(void)
{
	return nrf_write_cmd_only(NRF_CMD_FLUSH_RX);
}
/********************************
Descrip:  read RX-payload width in the RX FIFO.
Arg    :  none
Return :  payload width, used for nrf_rx_read_payload() 
*********************************/ 
char nrf_rx_payload_wid(void)
{
	char wid = 0;
	nrf_cmd_read(NRF_CMD_R_RX_PL_WID, &wid, 1);
	return wid;
}
/********************************
Descrip:  read RX-payload: 1 – 32 bytes. 
Arg    :  buf    - buffer for data saving
          rdlen  - number of bytes to read
Return :  current value of STATUS reg
*********************************/
char nrf_rx_read_payload(char* buf, char rdlen)
{
	return nrf_cmd_read(NRF_CMD_R_RX_PAYLOAD, buf, rdlen);
}
/********************************
Descrip:  flush TX FIFO
Arg    :  none
Return :  current value of STATUS reg
*********************************/
char nrf_tx_flush(void)
{
	return nrf_write_cmd_only(NRF_CMD_FLUSH_TX);
}
/********************************
Descrip:  reuse last transmitted payload.
Arg    :  none
Return :  current value of STATUS reg
*********************************/
char nrf_tx_reuse_payload(void)
{
	return nrf_write_cmd_only(NRF_CMD_REUSE_TX_PL);
}
/********************************
Descrip:  Write TX-payload, 1 – 32 bytes. 
Arg    :  buf    - buffer for data saving
          wrlen  - number of bytes to write
Return :  current value of STATUS reg
*********************************/
char nrf_tx_write_payload(char* buf, char wrlen)
{
	return nrf_cmd_write(NRF_CMD_W_TX_PAYLOAD, buf, wrlen);
}
/********************************
Descrip:  read the STATUS register
Arg    :  none
Return :  current value of STATUS reg
*********************************/
char nrf_status(void)
{
	return nrf_write_cmd_only(NRF_CMD_NOP);
} 
/********************************
Descrip:  write payload to be transmitted together with ACK packet on pipe.
Arg    :  pipe   - valid in the range: NRF_PIPE0 ~ NRF_PIPE5
          buf    - buffer for data saving
          wrlen  - number of bytes to write
Return :  current value of STATUS reg
*********************************/
char nrf_ack_write_payload(char pipe, char* buf, char wrlen)
{
	return nrf_cmd_write(NRF_CMD_W_ACK_PAYLOAD(pipe), buf, wrlen);
}
//
void nrf_power_up(void)
{
	char cfg = nrf_reg_read_byte(NRF_REG_CONFIG);
	if(!(cfg&(1<<NRF_BIT_PWR_UP)))
	{//set power up
		nrf_reg_write_byte(NRF_REG_CONFIG, cfg|(1<<NRF_BIT_PWR_UP));
	}
	NRF_DELAY_mS(2); //start up 1.5ms
}

void nrf_power_down(void)
{
	char cfg = nrf_reg_read_byte(NRF_REG_CONFIG);
	if(cfg&(1<<NRF_BIT_PWR_UP))   
	{//set power down
		cfg &= ~(char)(1<<NRF_BIT_PWR_UP); //clear bit
		nrf_reg_write_byte(NRF_REG_CONFIG, cfg);
	}
	NRF_DELAY_uS(1);
}
//mode - 0-PTX / 1-PRX
void nrf_set_primary_mode(char mode)
{
	if(mode<2)
	{
		char cfg = nrf_reg_read_byte(NRF_REG_CONFIG);
		//set bit,Enable CRC
		cfg |= (1<<NRF_BIT_EN_CRC);  
		//clr bit,CRC encoding scheme: 1 byte    
		cfg &= ~(char)((1<<NRF_BIT_CRCO)|(1<<NRF_BIT_PRIM_RX)); 
		//set mode
		cfg |= mode;
		nrf_reg_write_byte(NRF_REG_CONFIG, cfg);
	}
}
//set pipe address width, common for all data pipes.
//must be set before nrf_set_pipe_addr()/nrf_set_tx_addr()
//wid - must be one of the three values: 
//      NRF_VAL_AW_3Bytes
//      NRF_VAL_AW_4Bytes
//      NRF_VAL_AW_5Bytes
void nrf_set_addr_wid(char wid)
{
	nrf_reg_write_byte(NRF_REG_SETUP_AW, wid);
}
//set receive address for data pipe.
//pipe - pipe number, range: NRF_PIPE0~NRF_PIPE5
//addr - address buffer, MSBytes first for easy-reading.
//       e.g. { 0xA4, 0xA3, 0xA2, 0xA1, 0xA0 } (5bytes)
//len  - number of address bytes to write
void nrf_set_pipe_addr(char pipe, char* addr, char len)
{
	if((pipe>=NRF_PIPE0)&&(pipe<=NRF_PIPE5)&&(len>0)&&(len<=5))
	{//valid
		char* p;
		char adrtmp[5];
		if(pipe>=NRF_PIPE2)
		{//only use last byte
			addr += (len-1);
			len   = 1;
		}
		//LSBytes first 
		p = adrtmp;
		addr += (len-1);
		for(char i=0; i<len; i++)	
		{
			*p = *addr;
			p++;
			addr--;
		}
		nrf_reg_write_buf(NRF_REG_RX_ADDR_P0+pipe, adrtmp, len);
	}
}
//set transmit address, used for PTX only
//addr - address buffer, MSBytes first for easy-reading.
//       e.g. { 0xA4, 0xA3, 0xA2, 0xA1, 0xA0 } (5bytes)
//len  - number of address bytes to write
void nrf_set_tx_addr(char* addr, char len)
{
	if((len>0)&&(len<=5))
	{
		char adrtmp[5];
		char* p = adrtmp;
		//LSBytes first 
		addr += (len-1);
		for(char i=0; i<len; i++)	
		{
			*p = *addr;
			p++;
			addr--;
		}
		nrf_reg_write_buf(NRF_REG_TX_ADDR, adrtmp, len);
	}
}
//enable a data pipe
//pipe - pipe number, range: NRF_PIPE0~NRF_PIPE5
void nrf_pipe_enable(char pipe)
{
	if((pipe>=NRF_PIPE0)&&(pipe<=NRF_PIPE5))
	{
		char val;
		//enable [Dynamic Payload Length] and [Payload with ACK] (common for for all data pipes)
		nrf_reg_write_byte(NRF_REG_FEATURE, (1<<NRF_BIT_EN_DPL)|(1<<NRF_BIT_EN_ACK_PAY));
		//enable RX address of pipe
		val = nrf_reg_read_byte(NRF_REG_EN_RXADDR);
		val |= (1<<pipe);
		nrf_reg_write_byte(NRF_REG_EN_RXADDR, val);
		//enable auto-ACK for pipe
		val = nrf_reg_read_byte(NRF_REG_EN_AA);
		val |= (1<<pipe);
		nrf_reg_write_byte(NRF_REG_EN_AA, val);
		//enable Dynamic Payload Length for pipe
		val = nrf_reg_read_byte(NRF_REG_DYNPD);
		val |= (1<<pipe);
		nrf_reg_write_byte(NRF_REG_DYNPD, val);
	}
		
}
//get status of TX-FIFO and RX-FIFO
//return fifo status byte, used by 
//     NRF_FIFO_STATUS_TXREUSE()
//     NRF_FIFO_STATUS_TXFULL()
//     NRF_FIFO_STATUS_TXEMPTY()
//     NRF_FIFO_STATUS_RXFULL()
//     NRF_FIFO_STATUS_RXEMPTY()
char nrf_fifo_status(void)
{
	return nrf_reg_read_byte(NRF_REG_FIFO_STATUS);
}
//clear IRQ sources
//src_bits - range: 0x00~0x07                                                          
//           bit 7 ~ 3     2      1      0                               
//               NA  NA  RX_DR  TX_DS  MAX_RT                            
//                         0      1      0   : 0x02 - clr TX_DS only      
//                         1      0      1   : 0x05 - clr RX_DR and MAX_RT
//                         1      1      1   : 0x07 - clr all             
void nrf_clear_irq_src(char src_bits)
{
	src_bits &= 0x07;
	nrf_reg_write_byte(NRF_REG_STATUS, src_bits<<4);
}
//freq - 2400~2525 MHz
void nrf_set_rf_channel(uint16_t freq)
{
	nrf_reg_write_byte(NRF_REG_RF_CH, (char)(freq-2400));
}
//rate - one of NRF_VAL_RF_DR_250kbps
//              NRF_VAL_RF_DR_1Mbps
//              NRF_VAL_RF_DR_2Mbps 
void nrf_set_rf_data_rate(char rate)
{
	//default RF power : 0dBm
	nrf_reg_write_byte(NRF_REG_RF_SETUP, (char)(rate|NRF_VAL_RF_PWR_0dBm));
}
//delay - Auto Retransmit Delay, 
//        range: [NRF_VAL_ARD_250uS~NRF_VAL_ARD_4000uS]
//        delay = NRF_VAL_ARD_MAKE(delay_us)
//retry - Auto Retransmit Count, 
//        range: [NRF_VAL_ARC_none, NRF_VAL_ARC_1time~NRF_VAL_ARC_15time]
//        retry = NRF_VAL_ARC_MAKE(try_time)
void nrf_set_auto_retrans(char delay, char retry)
{
	nrf_reg_write_byte(NRF_REG_SETUP_RETR, (delay&0xF0)|retry);
}
